package common

import akka.actor.ActorSystem
import akka.event.Logging
import akka.http.scaladsl.Http
import akka.http.scaladsl.server.Route
import akka.stream.ActorMaterializer
import akka.stream.scaladsl.Sink
import helpers._

import scala.util._

class HttpServer(
    val boot: Bootstrap,
    val configuration: Configuration,
    val service: String
) extends HttpServerConfig
    with AccessLogging
    with ExtendRequestDirectives
    with JsonProtocol {

  val systemName: String    = sys.env.getOrElse("BUNDLE_SYSTEM", "AdminSystem")
  val systemVersion: String = sys.env.getOrElse("BUNDLE_SYSTEM_VERSION", "1")
  implicit val actorSystem: ActorSystem =
    ActorSystem(s"$systemName-$systemVersion", configuration.underlying)
  implicit val materializer: ActorMaterializer = ActorMaterializer()

  import actorSystem.dispatcher

  val log = Logging(actorSystem, "AccessLogging")

  //Boot up each service module from the config and get the routes
  val routes: List[Route]  = boot.bootup.map(_.routes)
  val definedRoutes: Route = routes.reduce(_ ~ _)

  val finalRoutes
      : Route = requestWrapper(definedRoutes) //accessLogging(log)(requestWrapper(definedRoutes)) //~ new HealthRoutes().routes

  val serverSource = Http().bind(interface = serverHost, port = serverPort)
  val sink         = Sink.foreach[Http.IncomingConnection](_.handleWith(finalRoutes))
  val startFuture  = serverSource.to(sink).run

  Logger.info("Starting up on port {} and ip {}", serverPort, serverHost)
  startFuture.onComplete {
    case Success(b) ⇒
      Logger.info(s"Server started on $serverHost:$serverPort")
      sys.addShutdownHook {
        b.unbind()
        actorSystem.terminate()
        Logger.info("Server stopped")
      }
    case Failure(e) ⇒
      Logger.error(s"Cannot start server on $serverHost:$serverPort", e)
      sys.addShutdownHook {
        actorSystem.terminate()
        Logger.info("Server stopped")
      }
  }
}
